﻿using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Newtonsoft.Json;

namespace Demo_jwt_core2
{
    public static class AuthExtension
    {
        public static void AddAuthorize(this IApplicationBuilder applicationBuilder)
        {
            applicationBuilder.Use(async (currentContext, nextContext) =>
            {
                //获取是否具有自定义的auth特性
                var authAttribute = currentContext.GetEndpoint()?.Metadata.GetMetadata<AuthAttribute>();
                if (authAttribute != null)
                {
                    if (currentContext.Request.Headers.ContainsKey("Authorization"))
                    {
                        var authorize = currentContext.Request.Headers["Authorization"].ToString();
                        if (authorize.Contains("Bearer"))
                        {
                            var info = authorize.Replace("Bearer ", string.Empty);
                            var jwtStr = info.Split('.').ToArray();
                            //声明hs256对象
                            var hs256 = new HMACSHA256(Encoding.UTF8.GetBytes(Const.SecurityKey));
                            //生成signature
                            var signature = Base64UrlTextEncoder.Encode(hs256.ComputeHash(Encoding.UTF8.GetBytes(jwtStr[0] + "." + jwtStr[1])));
                            //验证加密后是否相等
                            if (jwtStr[2] == signature)
                            {
                                //验证是否在有效时间内
                                var now = DateTime.UtcNow.ToUniversalTime();
                                var payload = JsonConvert.DeserializeObject<Dictionary<string, object>>(Encoding.UTF8.GetString(Base64UrlTextEncoder.Decode(jwtStr[1])));
                                if (now >= Convert.ToDateTime(payload["nbf"]) && now <= Convert.ToDateTime(payload["exp"]))
                                {
                                    //await currentContext.Response.WriteAsync("验证通过").ConfigureAwait(true);
                                    await nextContext?.Invoke();
                                    return;
                                }
                                currentContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                                await currentContext.Response.WriteAsync("Authorization time has passed, please log in again!").ConfigureAwait(true);
                            }
                        }
                    }
                    currentContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                    await currentContext.Response.WriteAsync("Verification failed, no permission to access!").ConfigureAwait(true);
                }
                await nextContext?.Invoke();
            });
        }
    }
}
